package com.train.mgr.modules.biz.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.train.common.enums.ProjectTypeEnum;
import com.train.common.exception.BizException;
import com.train.common.model.PageResult;
import com.train.common.model.SysUser;
import com.train.common.utils.AuthUtils;
import com.train.common.utils.DateUtils;
import com.train.mgr.config.redis.RedisUtil;
import com.train.mgr.config.thread.ThreadPool;
import com.train.mgr.modules.biz.dto.*;
import com.train.mgr.modules.biz.dto.request.LessonUserExerciseReqDTO;
import com.train.mgr.modules.biz.dto.request.TraineeExercisePageDTO;
import com.train.mgr.modules.biz.dto.request.TraineeLessionListReqDTO;
import com.train.mgr.modules.biz.dto.request.TraineeProjectReportReqDTO;
import com.train.mgr.modules.biz.dto.response.*;
import com.train.mgr.modules.biz.entity.*;
import com.train.mgr.modules.biz.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@RequiredArgsConstructor
@Service("ITraineeService")
public class TraineeServiceImpl implements ITraineeService {
    private final ICourseUserService courseUserService;
    private final ILessonUserExerciseService lessonUserExerciseService;
    private final ICourseService courseService;
    private final ILessonUserStudyService lessonUserStudyService;
    private final ILessonService lessonService;
    private final ICourseStuGroupRelService courseStuGroupRelService;
    private final IAnalysisCalService analysisCalService;
    private final RedisUtil redisUtil;
    @Override
    public TraineeCourseHomeDTO getCourseHome(Long courseId) {
        TraineeCourseHomeDTO dto = new TraineeCourseHomeDTO();
        //0：未通过，1：已通过，2:已提交申请
        Integer courseState = checkJoinCourseState(courseId);
        dto.setReviewStatus(courseState);
        List<TraineeCourseHomeVo> userCourse;
        switch (courseState){
            case 0:
            case 2:
                userCourse = courseUserService.getUserCourse(courseId);
                TraineeCourseHomeVoListTrans2Dto(courseState,dto,userCourse);
                dto.setIsJoinGroup(0);
                break;
            case 1:
                userCourse = courseUserService.getUserJoinCourse(courseId);
                TraineeCourseHomeVoListTrans2Dto(courseState,dto,userCourse);
                List<String> lessonIds = dto.getLessons().stream().map(TraineeCourseHomeDTO.LessonDTO::getLessonId).collect(Collectors.toList());
                LambdaQueryWrapper<LessonUserStudy> q = Wrappers.lambdaQuery();
                q.eq(LessonUserStudy::getCourseId,courseId);
                q.eq(LessonUserStudy::getIsDeleted,0);
                q.in(CollUtil.isNotEmpty(lessonIds),LessonUserStudy::getLessonId,lessonIds);
                q.eq(LessonUserStudy::getUserId,AuthUtils.getCurrentUser().getId());
                List<LessonUserStudy> list1 = lessonUserStudyService.list(q);
                dto.setFinishLessonCount((int) list1.stream().filter(e -> e.getIsFinish() !=null && e.getIsFinish().equals(1)).count());
                LambdaQueryWrapper<CourseStuGroupRel> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(CourseStuGroupRel::getCourseId,courseId);
                queryWrapper.eq(CourseStuGroupRel::getUserId,AuthUtils.getCurrentUser().getId());
                List<CourseStuGroupRel> list = courseStuGroupRelService.list(queryWrapper);
                if (CollUtil.isNotEmpty(list)){
                    dto.setIsJoinGroup(1);
                } else {
                    dto.setIsJoinGroup(0);
                }
                break;
        }
        return dto;
    }

    @Override
    public List<TraineeExerciseDTO> getCourseHomeExercise(Long courseId) {
        List<TraineeExerciseDTO> courseHomeExercise = lessonUserExerciseService.getCourseHomeExercise(courseId,null,null," ex.finish_time desc  LIMIT 10");
        for (TraineeExerciseDTO dto : courseHomeExercise) {
            Integer exerciseType = dto.getExerciseType();
            ProjectTypeEnum byCode = ProjectTypeEnum.getByCode(exerciseType);
            dto.setExerciseTypeName(byCode.getRemark());
        }
        return courseHomeExercise;
    }

    @Override
    public PageResult<TraineeAllExerciseDTO> getAllExercise(TraineeExercisePageDTO dto) {
        Page<TraineeAllExerciseDTO> page = dto.buildPage();
        dto.setUserId(AuthUtils.getCurrentUser().getId());
        Page<TraineeAllExerciseDTO> myExerciseList =lessonUserExerciseService.getMyExerciseList(page,dto);
        List<TraineeAllExerciseDTO> records = myExerciseList.getRecords();
        for (TraineeAllExerciseDTO exe : records) {
            String files = exe.getFiles();
            if (StrUtil.isNotBlank(files)){
                exe.setExerciseFiles(JSON.parseArray(files, LessonUserExerciseReqDTO.FileDto.class));
            }
        }
        return PageResult.of(myExerciseList, TraineeAllExerciseDTO.class);
    }

    @Override
    public JoinCourseDTO joinHomeCourse(Long courseId) {
        JoinCourseDTO dto = new JoinCourseDTO();
        Integer courseState = checkJoinCourseState(courseId);
        int reviewStatus;
        SysUser currentUser = AuthUtils.getCurrentUser();
        if (currentUser==null){
            throw new BizException("请先登录");
        }
        if (courseState.equals(0)){
            Course course = courseService.getById(courseId);
            if (course!=null && course.getIsPublish().equals(1) && course.getIsDeleted().equals(0)){
                // 如果未通过，判断加入课程是否需要审核，不需要审核，则加入该课程返回已通过
                CourseUser courseUser = new CourseUser();
                courseUser.setCourseId(courseId);
                courseUser.setUserId(currentUser.getId());
                courseUser.setNickName(currentUser.getNickName());
                courseUser.setUserName(currentUser.getUsername());
                courseUser.setCustomerId(currentUser.getCustomerId());
                courseUser.setReviewStatus(0);
                courseUser.setIsFinish(0);
                Integer reviewState = course.getReviewState();
                if (reviewState.equals(0)){
                    courseUser.setReviewStatus(1);
                    reviewStatus = 1;
                } else {
                    courseUser.setReviewStatus(2);
                    reviewStatus = 2;
                }
                courseUserService.save(courseUser);
            } else {
                throw new BizException("该课程不存在！");
            }
        } else {
            reviewStatus = courseState;
        }
        dto.setReviewStatus(reviewStatus);
        return dto;
    }

    @Override
    public TraineeOnStudyReqpDTO onStudy(TraineeLessionListReqDTO req) {
        Long courseId = req.getCourseId();
        if (courseId==null){
            throw new BizException("请选择课程！");
        }
        TraineeOnStudyReqpDTO dto = new TraineeOnStudyReqpDTO();
        //1、检查学员是否已完成课程
        List<TraineeCourseHomeVo> traineeCourseUser = courseUserService.getTraineeCourseUser(courseId);
        if (CollUtil.isEmpty(traineeCourseUser)){
            throw new BizException("请先加入课程！");
        }

        TraineeCourseHomeVo traineeCourseHomeVo = traineeCourseUser.get(0);
//        if (traineeCourseHomeVo.getIsFinished().equals(1)){
//            throw new BizException("该课程已学习完成！");
//        }

        String deadline = traineeCourseHomeVo.getDeadline();
        if (StrUtil.isNotBlank(deadline) && DateUtil.date().after(DateUtil.parse(deadline))){
            dto.setDeadlineState(1);
        } else {
            dto.setDeadlineState(0);
        }
        List<TranieeStudyReport> projects ;
        List<TranieeStudyReport> reports = new ArrayList<>();
        Long lessonId = req.getLessonId();
        if (lessonId == null){
            throw new BizException("课时不能为空！");
        }
        //2、检查学员是否有学习记录
        List<LessonUserStudy> userStudyList = lessonUserStudyService.getUserStudyList(courseId,lessonId);
        Lesson one = lessonService.getById(lessonId);
        if (one==null || one.getIsDeleted().equals(1) || one.getIsPublish().equals(0)){
            throw new BizException("学员未加入课时！");
        }
        dto.setKeywords(one.getKeywords());
        dto.setLessonName(one.getLessonName());
        dto.setSalesMethods(one.getSalesMethods());
        dto.setCourseId(courseId);
        dto.setLessonOrder(String.valueOf(one.getLessonOrder()));
        dto.setDeadline(deadline);
        dto.setLessonId(one.getId());
        String salesLanguage = one.getSalesLanguage();
        if (StrUtil.isNotBlank(salesLanguage)){
            try {
                dto.setSalesLanguageMap(new ObjectMapper().readValue(salesLanguage, Map.class));
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }
        if (CollUtil.isEmpty(userStudyList)){
            LessonUserStudy study = new LessonUserStudy();
            study.setCourseId(courseId);
            study.setLessonId(one.getId());
            study.setUserId(AuthUtils.getCurrentUser().getId());
            study.setCustomerId(one.getCustomerId());
            List<StudyFinishSituationVo> studyFinishSituationVos = new ArrayList<>();
            String practiceProject = one.getPracticeProject();
            if (StrUtil.isNotBlank(practiceProject)) {
                String[] split = practiceProject.split(",");
                for (String s : split) {
                    StudyFinishSituationVo vo = new StudyFinishSituationVo();
                    vo.setExerciseType(Integer.parseInt(s));
                    ProjectTypeEnum typeEnum = ProjectTypeEnum.getByCode(Integer.parseInt(s));
                    vo.setName(typeEnum.getRemark());
                    vo.setState(0);
                    studyFinishSituationVos.add(vo);
                }
            }
            projects = studyFinishSituationVos.stream().map(vo -> {
                TranieeStudyReport report = new TranieeStudyReport();
                report.setName(vo.getName());
                report.setState(vo.getState());
                report.setExerciseId(null);
                report.setExerciseType(vo.getExerciseType());
                return  report;
            }).collect(Collectors.toList());
            study.setStudySituation(JSON.toJSONString(studyFinishSituationVos));
            lessonUserStudyService.save(study);
//            //保存练习表
//            for (TranieeStudyReport project : projects) {
//                LessonUserExerciseReqDTO lessonUserExerciseReqDTO = new LessonUserExerciseReqDTO();
//                lessonUserExerciseReqDTO.setLessonUserStudyId(study.getId());
//                lessonUserExerciseReqDTO.setExerciseType(project.getExerciseType());
//                saveExercise(lessonUserExerciseReqDTO);
//            }
            dto.setStudyId(study.getId());
            dto.setIsFinish(0);
        } else {
            LessonUserStudy now = userStudyList.get(0);
            if (now ==null){
                throw new BizException("找不到对应的学习记录！");
            }
            dto.setStudyId(now.getId());
            projects = JSONArray.parseArray(now.getStudySituation(), TranieeStudyReport.class);
            dto.setIsFinish(now.getIsFinish());
            if (lessonId == null){
                lessonId = now.getLessonId();
            }
        }
        // 找到每个项目，获取到最新那一次练习的报告
        for (TranieeStudyReport project : projects) {
            Integer isFinish = project.getState();
            TranieeStudyReport report = new TranieeStudyReport();
            report.setName(project.getName());
            report.setState(isFinish);
            report.setExerciseType(project.getExerciseType());
            if (lessonId != null){
                List<LessonUserExercise> exercises = lessonUserExerciseService.getByProjectTypeLessonId(project.getExerciseType(), lessonId);
                if (CollUtil.isNotEmpty(exercises)){
                    LessonUserExercise exercise = exercises.get(0);
                    project.setExerciseState(exercise.getExerciseState());
                    report.setExerciseId(exercise.getId());
                    BeanUtils.copyProperties(exercise,report);
                    report.setExerciseFiles(JSONArray.parseArray(exercise.getExerciseFiles(),LessonUserExerciseReqDTO.FileDto.class));
                }
            }
            reports.add(report);
        }
        dto.setStudySituation(reports);
        return dto;
    }

    @Override
    public TraineeLessionListRespDTO getLessionListByCourseId(TraineeLessionListReqDTO req) {
        Long courseId = req.getCourseId();
        if (courseId==null){
            throw new BizException("课程id不能为空！");
        }
        TraineeLessionListRespDTO dto = new TraineeLessionListRespDTO();
        TraineeCourseHomeDTO courseHome = getCourseHome(courseId);
        if (courseHome!=null){
            List<TraineeCourseHomeDTO.LessonDTO> lessons = courseHome.getLessons();
            dto.setLessons(lessons);
        }

        return dto;
    }

    @Override
    public TraineeOnStudyReqpDTO switchLesson(TraineeLessionListReqDTO req) {
        TraineeOnStudyReqpDTO dto = new TraineeOnStudyReqpDTO();
        Long lessonId = req.getLessonId();
        if (lessonId==null){
            throw new BizException("课时id不能为空！");
        }
        Lesson one = lessonService.getBaseMapper().selectById(lessonId);
        if (one==null || one.getIsDeleted().equals(1) || one.getIsPublish().equals(0)){
            throw new BizException("课时不存在！");
        }
        List<LessonUserStudy> userStudyList = lessonUserStudyService.getUserStudyList(one.getCourseId(),lessonId);
        Long studyId;
        Integer isFinish;
        String studySituation;
        if (CollUtil.isEmpty(userStudyList)){
            // 如果课时学习为空，则插入新一条数据
            // throw new BizException("课时不存在！");
            LessonUserStudy study  = new LessonUserStudy();
            study.setCourseId(one.getCourseId());
            study.setLessonId(lessonId);
            study.setCustomerId(one.getCustomerId());
            study.setUserId(AuthUtils.getCurrentUser().getId());
            study.setCreateBy(AuthUtils.getCurrentUser().getId().toString());
            study.setCreateTime(new Date());
            List<StudyFinishSituationVo> studyFinishSituationVos = new ArrayList<>();
            String practiceProject = one.getPracticeProject();
            if (StrUtil.isNotBlank(practiceProject)) {
                String[] split = practiceProject.split(",");
                for (String s : split) {
                    StudyFinishSituationVo vo = new StudyFinishSituationVo();
                    vo.setExerciseType(Integer.parseInt(s));
                    ProjectTypeEnum typeEnum = ProjectTypeEnum.getByCode(Integer.parseInt(s));
                    vo.setName(typeEnum.getRemark());
                    vo.setState(0);
                    studyFinishSituationVos.add(vo);
                }
            }
            study.setStudySituation(JSON.toJSONString(studyFinishSituationVos));
            lessonUserStudyService.save(study);
            studyId = study.getId();
            isFinish = 0;
            studySituation = study.getStudySituation();
        } else {
            studyId = userStudyList.get(0).getId();
            isFinish = userStudyList.get(0).getIsFinish();
            studySituation = userStudyList.get(0).getStudySituation();
        }
        Course course = courseService.getById(one.getCourseId());
        if (course==null || course.getIsDeleted().equals(1) || course.getIsPublish().equals(0)){
            throw new BizException("课程不存在！");
        }
        if (course.getDeadline()!=null && DateUtil.date().after(course.getDeadline())){
            dto.setDeadlineState(1);
        } else {
            dto.setDeadlineState(0);
        }
        dto.setKeywords(one.getKeywords());
        dto.setLessonName(one.getLessonName());
        dto.setSalesMethods(one.getSalesMethods());
        dto.setCourseId(one.getCourseId());
        dto.setLessonOrder(String.valueOf(one.getLessonOrder()));
        dto.setStudyId(studyId);
        dto.setLessonId(lessonId);
        dto.setIsFinish(isFinish);
        List<TranieeStudyReport> projects = JSONArray.parseArray(studySituation, TranieeStudyReport.class);
        String salesLanguage = one.getSalesLanguage();
        if (StrUtil.isNotBlank(salesLanguage)){
            try {
                dto.setSalesLanguageMap(new ObjectMapper().readValue(salesLanguage, Map.class));
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }
        List<TranieeStudyReport> reports = new ArrayList<>(projects.size());
        // 获取到最新那一次练习的报告
        for (TranieeStudyReport project : projects) {
            Integer isFinishState = project.getState();
            TranieeStudyReport report = new TranieeStudyReport();
            report.setName(project.getName());
            report.setExerciseType(project.getExerciseType());
            report.setState(isFinishState);

            List<LessonUserExercise> exercises = lessonUserExerciseService.getByProjectTypeLessonId(project.getExerciseType(), lessonId);
            if (CollUtil.isNotEmpty(exercises)){
                LessonUserExercise exercise = exercises.get(0);
                project.setExerciseState(exercise.getExerciseState());
                BeanUtils.copyProperties(exercise,report);
                report.setExerciseId(exercise.getId());
                report.setExerciseFiles(JSONArray.parseArray(exercise.getExerciseFiles(),LessonUserExerciseReqDTO.FileDto.class));
            }

            reports.add(report);
        }
        dto.setStudySituation(reports);
        return dto;
    }

    @Override
    public TraineeStudyExerciseRespDTO getProjectReport(TraineeProjectReportReqDTO req) {
        TraineeStudyExerciseRespDTO dto = new TraineeStudyExerciseRespDTO();
        List<TraineeExerciseDTO> courseHomeExercise = lessonUserExerciseService.getCourseHomeExercise(req.getCourseId(),req.getLessonId(),req.getExerciseType(),"ORDER BY ex.exercise_number desc");
        if (CollUtil.isEmpty(courseHomeExercise)){
            return dto;
        }
        TraineeExerciseDTO dto1 = courseHomeExercise.get(0);
        BeanUtils.copyProperties(dto1,dto);
        List<TraineeExerciseDTO> exerciseList = new ArrayList<>(courseHomeExercise.size());
        for (int i = 1; i < courseHomeExercise.size(); i++) {
            exerciseList.add(courseHomeExercise.get(i));
        }
        dto.setExerciseList(exerciseList);
        return dto;
    }

    @Override
    public TraineeStudyExerciseRespDTO  getReport(Long exerciseId) {
        TraineeStudyExerciseRespDTO dto = new TraineeStudyExerciseRespDTO();

        // 兼容返回0分时，生成报告状态为3
        //Object o = redisUtil.get("report:" + exerciseId);
        //if (o!=null){
        //    log.info("exerciseId:{},报告生成状态：{}",exerciseId,o);
        //    dto.setIsGenerateReports(Integer.valueOf(o.toString()));
        //    return dto;
        //}

        List<TraineeExerciseDTO> dtos = lessonUserExerciseService.getReport(exerciseId);
        if (CollUtil.isEmpty(dtos)){
            // 兼容返回0分时，生成报告状态为3
            Object state = redisUtil.get("report:" + exerciseId);
            if (state!=null){
                log.info("exerciseId:{},报告生成状态：{}",exerciseId,state);
                dto.setIsGenerateReports(Integer.valueOf(state.toString()));
                return dto;
            }
            throw new BizException("报告不存在！");
        }
        dtos.forEach(item -> {
//            String useTime = item.getUseTime();
//            if (StrUtil.isNotBlank(useTime)){
//                BigDecimal minite = new BigDecimal(useTime).divide(BigDecimal.valueOf(60),0,RoundingMode.HALF_UP);
//                item.setUseTime(minite.toPlainString());
//            }
            String files = item.getFiles();
            if (StrUtil.isNotBlank(files)){
                item.setExerciseFiles(JSON.parseArray(files, LessonUserExerciseReqDTO.FileDto.class));
            }
        });
        dtos.stream().filter(x -> x.getExerciseId().equals(exerciseId)).findFirst().ifPresent(x -> {
            BeanUtils.copyProperties(x,dto);
        });
        BigDecimal max = dtos.stream().map(TraineeExerciseDTO::getComprehensiveScore).max(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal reduce = dtos.stream().map(TraineeExerciseDTO::getComprehensiveScore).reduce(BigDecimal.ZERO, BigDecimal::add);
        dto.setAvgScore(reduce.divide(new BigDecimal(dtos.size()), 1, RoundingMode.HALF_UP));
        dto.setMaxScore(max);
        dto.setExerciseList(dtos);
        return dto;
    }

    @Override
public List<TraineeStudyExerciseSearchRespDTO> getSearch() {
    List<TraineeStudyExerciseSearchVo> exerciseSearch = lessonUserExerciseService.getExerciseSearch(AuthUtils.getCurrentUser().getId());
    List<TraineeStudyExerciseSearchRespDTO> dtos = new ArrayList<>();
    
    if (CollUtil.isEmpty(exerciseSearch)) {
        return dtos;
    }
    
    Map<String, List<TraineeStudyExerciseSearchVo>> courseGroup = exerciseSearch.stream()
            .collect(Collectors.groupingBy(TraineeStudyExerciseSearchVo::getCourseId));
    
    courseGroup.forEach((courseId, courseExercises) -> {
        TraineeStudyExerciseSearchRespDTO courseDto = new TraineeStudyExerciseSearchRespDTO();
        courseDto.setCourseId(courseId);
        
        // 获取课程信息（取第一个元素）
        if (CollUtil.isNotEmpty(courseExercises)) {
            TraineeStudyExerciseSearchVo firstExercise = courseExercises.get(0);
            courseDto.setCourseName(firstExercise.getCourseName());
        }
        
        // 按课时分组
        Map<String, List<TraineeStudyExerciseSearchVo>> lessonGroup = courseExercises.stream()
                .collect(Collectors.groupingBy(TraineeStudyExerciseSearchVo::getLessonId));
        
        List<TraineeStudyExerciseSearchRespDTO.LessonDTO> lessonDtos = new ArrayList<>();
        lessonGroup.forEach((lessonId, lessonExercises) -> {
            if (CollUtil.isNotEmpty(lessonExercises)) {
                TraineeStudyExerciseSearchRespDTO.LessonDTO lessonDto = new TraineeStudyExerciseSearchRespDTO.LessonDTO();
                lessonDto.setLessonId(lessonId);
                lessonDto.setLessonName(lessonExercises.get(0).getLessonName());
                List<TraineeStudyExerciseSearchRespDTO.ExerciseDTO> collect = new ArrayList<>();

                TraineeStudyExerciseSearchRespDTO.ExerciseDTO exerciseDto1 = new TraineeStudyExerciseSearchRespDTO.ExerciseDTO();
                exerciseDto1.setExerciseType(ProjectTypeEnum.READING.getCode());
                exerciseDto1.setExerciseTypeName(ProjectTypeEnum.READING.getRemark());

                TraineeStudyExerciseSearchRespDTO.ExerciseDTO exerciseDto2 = new TraineeStudyExerciseSearchRespDTO.ExerciseDTO();
                exerciseDto2.setExerciseType(ProjectTypeEnum.PRACTICE.getCode());
                exerciseDto2.setExerciseTypeName(ProjectTypeEnum.PRACTICE.getRemark());

                TraineeStudyExerciseSearchRespDTO.ExerciseDTO exerciseDto3 = new TraineeStudyExerciseSearchRespDTO.ExerciseDTO();
                exerciseDto3.setExerciseType(ProjectTypeEnum.SIMULATED.getCode());
                exerciseDto3.setExerciseTypeName(ProjectTypeEnum.SIMULATED.getRemark());

                collect.add(exerciseDto1);
                collect.add(exerciseDto2);
                collect.add(exerciseDto3);
                lessonDto.setExercises(collect);
                lessonDtos.add(lessonDto);
            }
        });
        
        // 按课时顺序排序
        lessonDtos.sort(Comparator.comparing(TraineeStudyExerciseSearchRespDTO.LessonDTO::getLessonId));
        courseDto.setLessons(lessonDtos);
        dtos.add(courseDto);
    });
    
    // 按课程ID排序
    dtos.sort(Comparator.comparing(TraineeStudyExerciseSearchRespDTO::getCourseId));
    return dtos;
}

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String saveExercise(LessonUserExerciseReqDTO body) {
        LambdaQueryWrapper<LessonUserStudy> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LessonUserStudy::getLessonId,body.getLessonId());
        queryWrapper.eq(LessonUserStudy::getUserId,AuthUtils.getCurrentUser().getId());
        queryWrapper.eq(LessonUserStudy::getIsDeleted,0).last("limit 1");
        Lesson lesson = lessonService.getById(body.getLessonId());
        LessonUserStudy study = lessonUserStudyService.getOne(queryWrapper);
        Long studyId;
        if (study == null){
            LessonUserStudy lessonUserStudy = new LessonUserStudy();
            lessonUserStudy.setCourseId(lesson.getCourseId());
            lessonUserStudy.setLessonId(lesson.getId());
            lessonUserStudy.setUserId(AuthUtils.getCurrentUser().getId());
            lessonUserStudy.setCustomerId(lesson.getCustomerId());
            List<StudyFinishSituationVo> studyFinishSituationVos = new ArrayList<>();
            String practiceProject = lesson.getPracticeProject();
            if (StrUtil.isNotBlank(practiceProject)) {
                String[] split = practiceProject.split(",");
                for (String s : split) {
                    StudyFinishSituationVo vo = new StudyFinishSituationVo();
                    vo.setExerciseType(Integer.parseInt(s));
                    ProjectTypeEnum typeEnum = ProjectTypeEnum.getByCode(Integer.parseInt(s));
                    vo.setName(typeEnum.getRemark());
                    vo.setState(0);
                    studyFinishSituationVos.add(vo);
                }
            }
            lessonUserStudy.setStudySituation(JSON.toJSONString(studyFinishSituationVos));
            lessonUserStudyService.save(lessonUserStudy);
            studyId = lessonUserStudy.getId();
        } else {
            studyId = study.getId();
        }
        LessonUserExercise lessonUserExercise = new LessonUserExercise();
        LambdaQueryWrapper<LessonUserExercise> wrapper = Wrappers.<LessonUserExercise>lambdaQuery()
                .select(LessonUserExercise::getExerciseNumber)
                .eq(LessonUserExercise::getLessonUserStudyId, studyId)
                .eq(LessonUserExercise::getUserId, AuthUtils.getCurrentUser().getId())
                .eq(LessonUserExercise::getIsDeleted, 0)
                .eq(LessonUserExercise::getExerciseType, body.getExerciseType())
                .orderByDesc(LessonUserExercise::getExerciseNumber).last("limit 1");
        LessonUserExercise one = lessonUserExerciseService.getOne(wrapper);
        if (one != null){
            lessonUserExercise.setExerciseNumber(one.getExerciseNumber() + 1);
        } else {
            lessonUserExercise.setExerciseNumber(1);
        }
        BeanUtils.copyProperties(body, lessonUserExercise);
        lessonUserExercise.setUserId(AuthUtils.getCurrentUser().getId());
        lessonUserExercise.setCoruseId(lesson.getCourseId());
        List<LessonUserExerciseReqDTO.FileDto> files = body.getFiles();
        String filePath = null;
        List<String> imagePathList = new ArrayList<>();
        if (CollUtil.isNotEmpty(files)){
            imagePathList = files.stream().filter(file -> "IMAGE".equalsIgnoreCase(file.getFileType())).map(LessonUserExerciseReqDTO.FileDto::getFilePath).collect(Collectors.toList());
            List<LessonUserExerciseReqDTO.FileDto> fileDtoList = files.stream().filter(file -> "VIDEO".equalsIgnoreCase(file.getFileType())).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(fileDtoList)){
                filePath = fileDtoList.get(0).getFilePath();
            }
            redisUtil.set("report:"+lessonUserExercise.getId(),"1" , 60*60);
            lessonUserExercise.setIsGenerateReports(1);
            lessonUserExercise.setExerciseState(1);
            lessonUserExercise.setFinishTime(DateUtils.getTime());
            lessonUserExercise.setExerciseFiles(JSON.toJSONString(files));
        }
        lessonUserExercise.setLessonUserStudyId(studyId);
        lessonUserExercise.setLessonId(lesson.getId());
        lessonUserExercise.setCustomerId(AuthUtils.getCurrentUser().getCustomerId());
        lessonUserExercise.setCreateBy(AuthUtils.getUsername());
        lessonUserExercise.setCreateTime(new Date());
        String passingScore = lesson.getPassingScore();
        if (StrUtil.isNotBlank(passingScore)) {
            try {
                Map map = new ObjectMapper().readValue(passingScore, Map.class);
                Object o = map.get(body.getExerciseType().toString());
                if (o == null) {
                    throw new BizException("课时及格分数不存在！");
                }
                lessonUserExercise.setPassingScore(new BigDecimal(o.toString()));
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }
        //updateFinish(lessonUserExercise,lessonUserExercise.getComprehensiveScore(),lessonUserExercise.getPassingScore());

        lessonUserExerciseService.save(lessonUserExercise);

        toAiAnalys(lessonUserExercise,imagePathList,filePath);
        return lessonUserExercise.getId().toString();
    }

    /**/
    public void toAiAnalys(LessonUserExercise lessonUserExercise,
                           List<String> imagePathList,
                           String videoFilePath) {

        if (StrUtil.isBlank(videoFilePath) || CollUtil.isEmpty(imagePathList)) {
            return;
        }
        log.info("toAiAnalys 提交作品到AI");
        BigDecimal passingScore = lessonUserExercise.getPassingScore();

        // 一键异步：计算 + 落库 + 回调 全部在池子里完成
        ThreadPool.submit2Pool(() -> {
            long start = 0;
            try {
                AudioEvalDto calScoreMap = analysisCalService.getCalScoreMap(lessonUserExercise, videoFilePath);
                log.info("ExerciseID calScoreMap:{}", calScoreMap);
                start = System.currentTimeMillis();
//                BigDecimal comprehensiveScore = calScoreMap.getConfidenceScore()
//                        .add(calScoreMap.getSpeedVolumeScore())
//                        .add(calScoreMap.getFluencyScore())
//                        .add(calScoreMap.getCompletenessScore())
//                        .add(calScoreMap.getAccuracyScore())
//                        .divide(BigDecimal.valueOf(5), 1, RoundingMode.HALF_UP);

                // 1. 落库
//                LessonUserExercise update = new LessonUserExercise() {{
//                    setId(lessonUserExercise.getId());
//                    setAccuracyMessage(calScoreMap.getAccuracyWenAn());
//                    setFillWordsStuttering(calScoreMap.getAccuracyScore().toPlainString());
//                    setConfidenceMessage(calScoreMap.getConfidenceWenAn());
//                    setConfidence(calScoreMap.getConfidenceScore().toPlainString());
//                    setSpeedVolumeMessage(calScoreMap.getSpeedVolumeWenAn());
//                    setSpeedVolume(calScoreMap.getSpeedVolumeScore().toPlainString());
//                    setFluencyMessage(calScoreMap.getFluencyWenAn());
//                    setFluency(calScoreMap.getFluencyScore().toPlainString());
//                    setCompletenessMessage(calScoreMap.getCompletenessWenAn());
//                    setCompleteness(calScoreMap.getCompletenessScore().toPlainString());
//                    setComprehensiveScore(comprehensiveScore);
//                    setPassingState(comprehensiveScore.compareTo(passingScore) >= 0 ? 1 : 0);
//                    setIsGenerateReports(2);
//                    setAudioText(calScoreMap.getAudioText());
//                }};

                    BigDecimal comprehensiveScore = Stream.of(
                            Optional.ofNullable(calScoreMap.getConfidenceScore()).orElse(BigDecimal.ZERO),
                            Optional.ofNullable(calScoreMap.getSpeedVolumeScore()).orElse(BigDecimal.ZERO),
                            Optional.ofNullable(calScoreMap.getFluencyScore()).orElse(BigDecimal.ZERO),
                            Optional.ofNullable(calScoreMap.getCompletenessScore()).orElse(BigDecimal.ZERO),
                            Optional.ofNullable(calScoreMap.getAccuracyScore()).orElse(BigDecimal.ZERO))
                            .reduce(BigDecimal.ZERO, BigDecimal::add)
                            .divide(BigDecimal.valueOf(5), 1, RoundingMode.HALF_UP);

                    // 报告异常 ，需要返回状态为3
                    if(comprehensiveScore.compareTo(BigDecimal.ZERO) == 0){
                        redisUtil.set("report:"+lessonUserExercise.getId(),"3" , 60*60);
                        log.error("report_error,报告异常，需要返回状态为3。LessonUserExerciseId:{}",lessonUserExercise.getId());
                        LessonUserExercise update = new LessonUserExercise();
                        update.setIsGenerateReports(3);
                        update.setId(lessonUserExercise.getId());
                        update.setIsDeleted(1);
                        lessonUserExerciseService.updateById(update);
                        return;
                    }

                    LessonUserExercise update = new LessonUserExercise() {{
                        setId(lessonUserExercise.getId());
                        setAccuracyMessage(nullToEmpty(calScoreMap.getAccuracyWenAn()));
                        setFillWordsStuttering(nullToZero(calScoreMap.getAccuracyScore()).toPlainString());
                        setConfidenceMessage(nullToEmpty(calScoreMap.getConfidenceWenAn()));
                        setConfidence(nullToZero(calScoreMap.getConfidenceScore()).toPlainString());
                        setSpeedVolumeMessage(nullToEmpty(calScoreMap.getSpeedVolumeWenAn()));
                        setSpeedVolume(nullToZero(calScoreMap.getSpeedVolumeScore()).toPlainString());
                        setFluencyMessage(nullToEmpty(calScoreMap.getFluencyWenAn()));
                        setFluency(nullToZero(calScoreMap.getFluencyScore()).toPlainString());
                        setCompletenessMessage(nullToEmpty(calScoreMap.getCompletenessWenAn()));
                        setCompleteness(nullToZero(calScoreMap.getCompletenessScore()).toPlainString());

                        setComprehensiveScore(comprehensiveScore);
                        setPassingState(comprehensiveScore.compareTo(passingScore) >= 0 ? 1 : 0);
                        setIsGenerateReports(2);
                        setWpmAvgVoiced(calScoreMap.getWpmAvgVoiced());
                        setAudioText(nullToEmpty(calScoreMap.getAudioText()));
                }};
                lessonUserExerciseService.updateById(update);

                redisUtil.set("report:"+lessonUserExercise.getId(),"2" , 60*60);

                // 2. 回调（也在同一个异步线程里）
                updateFinish(lessonUserExercise, comprehensiveScore, passingScore);

                log.info("AI分析完成 & 回调成功 - exerciseId={}", lessonUserExercise.getId());
            } catch (Exception e) {
                log.error("AI分析异步任务失败 - exerciseId={}", lessonUserExercise.getId(), e);
                redisUtil.set("report:"+lessonUserExercise.getId(),"3" , 60*60);
                // 可选：落库失败标记
                LessonUserExercise err = new LessonUserExercise();
                err.setId(lessonUserExercise.getId());
                err.setIsGenerateReports(3);   // 3=生成失败
                err.setIsDeleted(1);
                lessonUserExerciseService.updateById(err);
            }finally {
                long cost = (System.currentTimeMillis() - start);
                log.info("五维度分数计算后开始计时的 总耗时: {} ms", cost);
            }
        });
    }


    BigDecimal nullToZero(BigDecimal src) {
        return src == null ? BigDecimal.ZERO : src;
    }
    String nullToEmpty(String src) {
        return src == null ? "" : src;
    }

/*

    public void toAiAnalysByWeijie(LessonUserExercise lessonUserExercise,List<String> imagePathList, String videoFilePath) {
        if (StrUtil.isNotBlank(videoFilePath) && CollUtil.isNotEmpty(imagePathList)){
            log.info("toAiAnalys 提交作品到AI");
            BigDecimal passingScore = lessonUserExercise.getPassingScore();
            ThreadPool.submit2Pool(() -> {
                AudioEvalDto calScoreMap = analysisCalService.getCalScoreMap(lessonUserExercise, videoFilePath);
                log.info("ExerciseID calScoreMap:{}",calScoreMap);

                //long audioDuration = calScoreMap.getAudioDuration() / 1000;
                BigDecimal comprehensiveScore = calScoreMap.getConfidenceScore()
                        .add(calScoreMap.getSpeedVolumeScore())
                        .add(calScoreMap.getFluencyScore())
                        .add(calScoreMap.getCompletenessScore())
                        .add(calScoreMap.getAccuracyScore()).divide(BigDecimal.valueOf(5),3,RoundingMode.HALF_UP);

                lessonUserExerciseService.updateById(new LessonUserExercise() {{
                    setId(lessonUserExercise.getId());
                    setAccuracyMessage(calScoreMap.getAccuracyWenAn());
                    setFillWordsStuttering(calScoreMap.getAccuracyScore().toPlainString());
                    setConfidenceMessage(calScoreMap.getConfidenceWenAn());
                    setConfidence(calScoreMap.getConfidenceScore().toPlainString());
                    setSpeedVolumeMessage(calScoreMap.getSpeedVolumeWenAn());
                    setSpeedVolume(calScoreMap.getSpeedVolumeScore().toPlainString());
                    setFluencyMessage(calScoreMap.getFluencyWenAn());
                    setFluency(calScoreMap.getFluencyScore().toPlainString());
                    setCompletenessMessage(calScoreMap.getCompletenessWenAn());
                    setCompleteness(calScoreMap.getCompletenessScore().toPlainString());
                    setComprehensiveScore(comprehensiveScore);
                    setPassingState(comprehensiveScore.compareTo(passingScore) >= 0 ? 1 : 0);
                    setIsGenerateReports(2);
                    setAudioText(calScoreMap.getAudioText());
                    setWpmAvgVoiced(calScoreMap.getWpmAvgVoiced());//净语速（2025-11-05添加）
                }});

                updateFinish(lessonUserExercise,comprehensiveScore,passingScore);

            });
        }
    } */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateExercise(LessonUserExerciseReqDTO body) {
        LessonUserExercise lessonUserExercise = lessonUserExerciseService.getById(body.getExerciseId());
        if (lessonUserExercise == null) {
            throw new BizException("练习项目不存在！");
        }
        BigDecimal comprehensiveScore = body.getComprehensiveScore();
        BigDecimal passingScore = lessonUserExercise.getPassingScore();
        lessonUserExercise.setCompleteness(body.getCompleteness());
        lessonUserExercise.setConfidence(body.getConfidence());
        lessonUserExercise.setFluency(body.getFluency());
        lessonUserExercise.setFillWordsStuttering(body.getFillWordsStuttering());
        lessonUserExercise.setSpeedVolume(body.getSpeedVolume());
        lessonUserExercise.setComprehensiveScore(comprehensiveScore);
        updateFinish(lessonUserExercise,comprehensiveScore,passingScore);
        return lessonUserExerciseService.updateById(lessonUserExercise);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateFinish(LessonUserExercise lessonUserExercise,BigDecimal comprehensiveScore, BigDecimal passingScore){
        log.info("更新课时，课程的完成状态");
        if (comprehensiveScore != null && passingScore != null && comprehensiveScore.compareTo(passingScore) >= 0) {
            lessonUserExercise.setPassingState(1);
            lessonUserExercise.setIsGenerateReports(2);
            lessonUserExercise.setFinishTime(DateUtil.formatDateTime(new Date()));

            // 更新study表，项目状态改为已完成
            LessonUserStudy study = lessonUserStudyService.getById(lessonUserExercise.getLessonUserStudyId());
            String studySituation = study.getStudySituation();
            List<StudyFinishSituationVo> studyFinishSituationVos = JSONArray.parseArray(studySituation, StudyFinishSituationVo.class);
            for (StudyFinishSituationVo studyFinishSituationVo : studyFinishSituationVos) {
                if (studyFinishSituationVo.getExerciseType().equals(lessonUserExercise.getExerciseType())) {
                    studyFinishSituationVo.setState(1);
                }
            }
            long count = studyFinishSituationVos.stream().filter(x -> x.getState().equals(0)).count();
            if (count == 0){
                study.setIsFinish(1);
                study.setFinishTime(new Date());
            }
            study.setStudySituation(JSON.toJSONString(studyFinishSituationVos));
            lessonUserStudyService.updateById(study);
            // 判断课时课时是否已全部完成，对应更新课程用户表的完成状态
            LambdaQueryWrapper<LessonUserStudy> queryWrapper = Wrappers.<LessonUserStudy>lambdaQuery()
                    .eq(LessonUserStudy::getCourseId, lessonUserExercise.getCoruseId())
                    .eq(LessonUserStudy::getUserId, lessonUserExercise.getUserId())
                    .eq(LessonUserStudy::getIsDeleted, 0);
            List<LessonUserStudy> list = lessonUserStudyService.list(queryWrapper);
            long finishCount = list.stream().filter(x -> x.getIsFinish()!= null && x.getIsFinish().equals(1)).count();
            LambdaQueryWrapper<Lesson> q = Wrappers.<Lesson>lambdaQuery()
                    .eq(Lesson::getCourseId, lessonUserExercise.getCoruseId())
                    .eq(Lesson::getIsDeleted, 0)
                    .eq(Lesson::getIsPublish, 1);
            long lessonCount = lessonService.count(q);
            if (finishCount == lessonCount){
                UpdateWrapper<CourseUser> wrapper = Wrappers.update();
                wrapper.set("is_finish",1);
                wrapper.set("finish_time",new Date());
                wrapper.eq("course_id",lessonUserExercise.getCoruseId());
                wrapper.eq("user_id",lessonUserExercise.getUserId());
                courseUserService.update(wrapper);
            }
        }
    }
    @Override
    public TraineeStuRespDTO getTrainee() {
        TraineeStuRespDTO stuCourseCount = courseService.getStuCourseCount();
        if (stuCourseCount == null){
            return new TraineeStuRespDTO();
        }
        TraineeStuRespDTO exerciseStuCount = lessonUserExerciseService.getExerciseStuCount();
        Integer exerciseTime = exerciseStuCount.getExerciseTime();
        if (exerciseTime != null && exerciseTime > 0){
            BigDecimal minite = new BigDecimal(exerciseTime).divide(new BigDecimal(60),0,RoundingMode.HALF_UP);
            stuCourseCount.setExerciseTime(minite.intValueExact());
        }
        stuCourseCount.setExerciseCount(exerciseStuCount.getExerciseCount());
        List<TraineeStuExerciseDTO> list = lessonUserExerciseService.getExerciseStuCountList();
        if (CollUtil.isNotEmpty(list)){
            for (TraineeStuExerciseDTO item : list) {
                ProjectTypeEnum projectTypeEnum = ProjectTypeEnum.getByCode(item.getExerciseType());
                if (projectTypeEnum != null) {
                    item.setExerciseTypeName(projectTypeEnum.getRemark());
                }
                String useTime = item.getUseTime();
                if (StrUtil.isNotBlank(useTime)){
                    BigDecimal minite = new BigDecimal(useTime).divide(new BigDecimal(60),0,RoundingMode.HALF_UP);
                    item.setUseTime(minite.toPlainString());
                }
            }
        }
        if (stuCourseCount.getExerciseTime() == null){
            stuCourseCount.setExerciseTime(0);
        }
        stuCourseCount.setExercises(list);
        return stuCourseCount;
    }


    /**
     * 检查加入课程状态
     * @return 0：未通过，1：已通过，2:已提交申请
     */
    private Integer checkJoinCourseState(Long courseId) {
        Integer integer = courseUserService.checkJoinCourseState(courseId);
        if (integer == null){
            integer =  0;
        }
        return integer;
    }

    private void TraineeCourseHomeVoListTrans2Dto(Integer courseState,TraineeCourseHomeDTO dto,List<TraineeCourseHomeVo>  vos) {
        if (CollUtil.isNotEmpty(vos)){
            TraineeCourseHomeVo traineeCourseHomeVo = vos.get(0);
            dto.setCourseId(traineeCourseHomeVo.getCourseId());
            dto.setIsSelfGroup(traineeCourseHomeVo.getIsSelfGroup());
            dto.setCourseName(traineeCourseHomeVo.getCourseName());
            dto.setCourseIntroduction(traineeCourseHomeVo.getCourseIntroduction());
            String deadline = traineeCourseHomeVo.getDeadline();
            dto.setDeadline(deadline);
            dto.setStudyUserCount(traineeCourseHomeVo.getStudyUserCount());
            long count = vos.stream().filter(x -> x.getIsFinished() != null && x.getIsFinished().equals(1)).count();
            long lessonCount = vos.stream().map(TraineeCourseHomeVo::getLessonId).distinct().count();
            dto.setLessonCount((int) lessonCount);
            dto.setFinishLessonCount((int) count);
            Integer isFinished = traineeCourseHomeVo.getIsFinished();
            dto.setIsFinished(isFinished);
            if (StrUtil.isNotBlank(deadline) && DateUtil.date().after(DateUtil.parse(deadline))){
                dto.setDeadlineState(1);
            } else {
                dto.setDeadlineState(0);
            }
            List<TraineeCourseHomeDTO.LessonDTO> lessons = new ArrayList<>();
            Map<String, List<TraineeCourseHomeVo>> lessonMap = vos.stream().collect(Collectors.groupingBy(TraineeCourseHomeVo::getLessonId));
            lessonMap.forEach((lessonId, lessonList)->{
                TraineeCourseHomeDTO.LessonDTO lessonDTO = new TraineeCourseHomeDTO.LessonDTO();
                TraineeCourseHomeVo lessonVo = lessonList.get(0);
                lessonDTO.setLessonId(lessonId);
                lessonDTO.setLessonName(lessonVo.getLessonName());
                lessonDTO.setLessonOrder(lessonVo.getLessonOrder());
                lessonDTO.setKeywords(lessonVo.getKeywords());
                lessonDTO.setLessonCreateTime(lessonVo.getLessonCreateTime());
                if (StrUtil.isNotBlank(lessonVo.getSalesLanguage())) {
                    try {
                        lessonDTO.setSalesLanguageMap(new ObjectMapper().readValue(lessonVo.getSalesLanguage(), Map.class));
                    } catch (JsonProcessingException e) {
                        throw new RuntimeException(e);
                    }
                }
                if (isFinished != null && isFinished.equals(1)) {
                    lessonDTO.setLessonFinishCompletion("1");
                } else {
                    lessonDTO.setLessonFinishCompletion("0");
                }
                String studySituation = lessonVo.getStudySituation();
                if (StrUtil.isNotBlank(studySituation)) {
                    List<StudyFinishSituationVo> studyFinishSituationVos = JSONArray.parseArray(studySituation, StudyFinishSituationVo.class);
                    long count1 = studyFinishSituationVos.stream().filter(item -> item.getState().equals(1)).count();
                    if (count1 > 0){
                        BigDecimal divide = BigDecimal.valueOf(count1).divide(BigDecimal.valueOf(studyFinishSituationVos.size()), 2, RoundingMode.HALF_UP);
                        lessonDTO.setLessonFinishCompletion(divide.toPlainString());
                    }
                    if (count1 == 0){
                        lessonDTO.setLessonFinishCompletion("0");
                    }
                    lessonDTO.setPracticeProjects(studyFinishSituationVos);
                } else {
                    String practiceProject = lessonVo.getPracticeProject();
                    String[] split = practiceProject.split(",");
                    List<StudyFinishSituationVo> studyFinishSituationVos = new ArrayList<>();
                    for (String s : split) {
                        StudyFinishSituationVo studyFinishSituationVo = new StudyFinishSituationVo();
                        ProjectTypeEnum byCode = ProjectTypeEnum.getByCode(Integer.valueOf(s));
                        studyFinishSituationVo.setExerciseType(byCode.getCode());
                        studyFinishSituationVo.setName(byCode.getRemark());
                        studyFinishSituationVo.setState(0);
                        studyFinishSituationVos.add(studyFinishSituationVo);
                    }
                    lessonDTO.setPracticeProjects(studyFinishSituationVos);
                }
                List<FileDto> fileDtos = lessonList.stream().filter(item -> item.getFileId() != null).map(item -> {
                    FileDto fileDto = new FileDto();
                    fileDto.setId(item.getFileId());
                    fileDto.setFilePath(item.getFilePath());
                    fileDto.setFileSize(item.getFileSize());
                    fileDto.setFileType(item.getFileType());
                    fileDto.setFileExtension(item.getFileExtension());
                    fileDto.setFileName(item.getFileName());
                    return fileDto;
                }).collect(Collectors.toList());
                lessonDTO.setFiles(fileDtos);

                lessons.add(lessonDTO);
            });
            List<TraineeCourseHomeDTO.LessonDTO> orderLessons = lessons.stream().sorted(Comparator.comparing(TraineeCourseHomeDTO.LessonDTO::getLessonCreateTime)).collect(Collectors.toList());
            dto.setLessons(orderLessons);
        }
    }
}
